package com.xunmall.account.service.impl;

import com.google.common.collect.Maps;
import com.xunmall.account.dto.RoleDto;
import com.xunmall.account.dto.UrlDto;
import com.xunmall.account.entity.RoleDO;
import com.xunmall.account.mapper.RoleMapper;
import com.xunmall.account.service.RoleService;
import com.xunmall.base.exception.BadRequestException;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @Author: WangYanjing
 * @Date: 2018/12/27 10:53
 * @Description:
 */
@Service
public class RoleServiceImpl implements RoleService {

    @Autowired
    RoleMapper roleMapper;

    @Override
    @Transactional(readOnly = true)
    public Map<String, List<UrlDto>> getMetaSource() {
        Map<String, List<UrlDto>> result = Maps.newHashMap();

        List<Map<String, String>> permsMetaSources = roleMapper.getMetaSource();
        List<UrlDto> perms = parseMetaSource(permsMetaSources);
        result.put("perms", perms);
        List<Map<String, String>> defaultMetaSources = roleMapper.getDefaultMetaSource("0");
        List<UrlDto> defaults = parseMetaSource(defaultMetaSources);
        result.put("defaults", defaults);
        List<Map<String, String>> holdUpMetaSources = roleMapper.getDefaultMetaSource("1");
        List<UrlDto> holdUp = parseMetaSource(holdUpMetaSources);
        result.put("holdUp", holdUp);

        return result;
    }

    private List<UrlDto> parseMetaSource(List<Map<String, String>> metaSources) {
        Map<String, Set<String>> methodPerms = new LinkedHashMap<>();
        //url=url-1  methods=GET,PUT  perms=EMPL_EXPORT,ATTE_CONF
        for (Map<String, String> metaSource : metaSources) {
            String url = metaSource.get("url");
            String methods = metaSource.get("methods") == null ? "" : metaSource.get("methods");
            for (String method : methods.split(",")) {
                String key = url.concat(",").concat(method);
                Set<String> perms = null;
                if (methodPerms.containsKey(key)) {
                    perms = methodPerms.get(key);
                } else {
                    perms = new HashSet<>();
                    methodPerms.put(key, perms);
                }
                String permsStr = metaSource.get("perms");
                CollectionUtils.addAll(perms, permsStr.split(","));
            }
        }
        List<UrlDto> urlDtos = new ArrayList<>();
        for (String key : methodPerms.keySet()) {
            UrlDto urlDto = new UrlDto();
            urlDto.setUrl(key.split(",")[0]);
            urlDto.setMethod(key.split(",").length > 1 ? key.split(",")[1] : "");
            urlDto.setPermissions(methodPerms.get(key));
            urlDtos.add(urlDto);
        }
        return urlDtos;
    }


    @Override
    public List<RoleDO> getByUser(String userId, String compId) {
        List<RoleDO> roleDOS = roleMapper.getRolesByUserId(userId, compId);
        return roleDOS;
    }

    @Override
    public List<RoleDO> getByComp(String compId) {
        RoleDO roleDO = new RoleDO();
        roleDO.setCompUuid(compId);
        List<RoleDO> roleDOS = roleMapper.select(roleDO);
        return roleDOS;
    }

    @Override
    public Boolean checkRoleCode(String roleCode) {
        RoleDO roleDO = new RoleDO();
        roleDO.setRoleCode(roleCode);
        List<RoleDO> roleDOS = roleMapper.select(roleDO);
        if (roleDOS.size() > 0) {
            return false;
        } else {
            return true;
        }
    }

    @Override
    public RoleDO create(RoleDO entity) {
        if (entity == null || StringUtils.isBlank(entity.getRoleName())) {
            throw new BadRequestException("error.account.0001", this, "roleName");
        }
        entity.buildForInsert();
        if (StringUtils.isEmpty(entity.getRoleCode())) {
            entity.setRoleCode(entity.getUuid());
        }
        // 校验是否重复
        boolean isUnique = checkRoleCode(entity.getRoleCode());
        if (!isUnique) {
            throw new BadRequestException("error.account.0004", this, "code");
        }
        int result = roleMapper.insertSelective(entity);
        if (result > 0) {
            return entity;
        } else {
            throw new BadRequestException("error.account.0002", this);
        }
    }

    private boolean checkDefault(String uuid) {
        return "GLOBAL".equals(roleMapper.selectByPrimaryKey(uuid).getCompUuid());
    }

    @Override
    public RoleDO update(RoleDO entity) {
        if (entity == null || StringUtils.isBlank(entity.getUuid())) {
            throw new BadRequestException("error.account.0001", this, "uuid");
        }
        if (checkDefault(entity.getUuid())) {
            throw new BadRequestException("error.account.0010", this);
        }
        RoleDO oldEntity = roleMapper.selectByPrimaryKey(entity.getUuid());
        if (oldEntity == null) {
            throw new BadRequestException("error.account.0003", this);
        }
        oldEntity.buildForUpdate();
        oldEntity.setRoleName(entity.getRoleName());
        oldEntity.setDescription(entity.getDescription());
        int result = roleMapper.updateByPrimaryKeySelective(oldEntity);
        if (result > 0) {
            return oldEntity;
        } else {
            throw new BadRequestException("error.account.0002", this);
        }
    }

    @Override
    public RoleDto getCompAdmin() {
        RoleDto roleDto = null;
        RoleDO roleDO = new RoleDO();
        roleDO.setCompUuid("GLOBAL");
        roleDO.setRoleLevel((short) 4);
        List<RoleDO> roleDOS = roleMapper.select(roleDO);
        if (roleDOS != null && roleDOS.size() > 0) {
            roleDto = new RoleDto();
            BeanUtils.copyProperties(roleDOS.get(0), roleDto);
        }
        return roleDto;
    }

    @Override
    public RoleDO getByUuid(String uuid) {
        return roleMapper.selectByPrimaryKey(uuid);
    }

    private boolean checkRela(String roleId) {
        return roleMapper.checkRela(roleId);
    }


    private void cleanAuthorization(String compId, String roleId) {
        roleMapper.cleanAuthorization(compId, roleId);
    }
}